package md.frolov.bible.indexes;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import md.frolov.bible.Activator;
import md.frolov.bible.Constants;

public class IndexManager {
	private static IndexManager instance;
	private Map <File,IX> indexes = new HashMap<File,IX>();

	/**
	 * returns IndexManager's instance 
	 * @return
	 */
	public static IndexManager getInstance(){
		if(instance == null) instance = new IndexManager();
		return instance;
	}
	
	public IX getIndex(File file){
		return indexes.get(file);
	}
	
	public long getOffset(File file, String key){
		return getIndex(file).getOffset(key);
	}
		
	public void addOffset(File file, String key, long offset){
		IX ix = getIndex(file);
		if(ix == null) throw new IllegalArgumentException();
		
		ix.addOffset(key, offset);
	}
	
	public void removeIndex(File file){
		indexes.remove(file);
	}
	
	public void init(){
		File root = Activator.getInstance().getStateLocation().toFile();
		searchIndexes(root);
	}
	
	private void searchIndexes(File file){
		if(file.isFile()){
			if(file.getName().endsWith(".ix")){
				try{
					parseFile(file);
					return;
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e){
					e.printStackTrace();
					//bad file, removing
					file.delete();
					return;
				}
			}
		} else { //isDirectory
			File[] list = file.listFiles();
			for(int i=0;i <list.length;i++){
				searchIndexes(list[i]);
			}
		}
	}
	
	private void parseFile(File ixFile) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(ixFile),Constants.ENCODING));
		try{
			String line1;
			String line2;
			IX ix;
			line1 = br.readLine();
			
			File file = Activator.getInstance().getWorkspace().append(line1).toFile();
			if(!file.exists()) throw new IllegalArgumentException();
			try{
				long lastModified = Long.valueOf(br.readLine()).longValue();
				if(file.lastModified()!=lastModified) throw new IllegalArgumentException();
				if(getIndex(file)!=null) throw new IllegalArgumentException();
				ix = createIndex(file, br.readLine());
			} catch (NumberFormatException e){
				throw new IllegalArgumentException();
			}
			
			while((line1=br.readLine())!=null && (line2=br.readLine())!=null){
				ix.addOffset(line1,Long.valueOf(line2));
			}
		} finally{
			br.close();
		}
	}

	public void save() throws IOException{
		File ws = Activator.getInstance().getStateLocation().toFile();
		Collection<IX> ixs = indexes.values();
		for (Iterator<IX> it = ixs.iterator(); it.hasNext();) {
			it.next().save(ws);
		}
	}
	
	public IX createIndex(File file, String type){
		IX res = null;
		if(type.equals(IXBible.class.getName())) res = new IXBible(file);
		if(type.equals(IXDictionary.class.getName())) res = new IXDictionary(file);
		if(res!=null){
			indexes.put(file, res);
			return res;
		}
		throw new IllegalArgumentException();
	}
}
